/*
 * Copyright (c) Huawei Technologies Co., Ltd. 2021-2022. All rights reserved.
 *
 */
import { describe, expect, test } from '@jest/globals';
import { Json5Reader } from '@ohos/hvigor';
import * as fse from 'fs-extra';
import { readdirSync } from 'fs-extra';
import * as path from 'path';
import { basename, resolve } from 'path';

import { CompileModeEnum } from '../../src/enum/compile-mode-enum';
import { ModuleJson } from '../../src/options/configure/module-json-options';

import { initByFABigService, initByStageEmptyApp, initExecuteCommand, runHvigor } from './common/common';
import { ModuleBuildProfileModifier } from './common/modifier/module-build-profile-modifier';
import { Probes } from './common/probes';
import ModuleOptObj = ModuleJson.ModuleOptObj;

describe('Stage App', () => {
  test.concurrent('stage app assembleHap jsbundle', async () => {
    await initByStageEmptyApp(async (dir) => {
      // 修改compileOptions
      const probe = new Probes(dir, resolve(dir, 'entry'));
      const entryBuildProfile = new ModuleBuildProfileModifier(dir, 'entry');
      entryBuildProfile.setCompileMode(CompileModeEnum.JS_BUNDLE)
        .outputSync();

      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        tasks: 'assembleHap'
      });
      const result = runHvigor(dir, commands);
      expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();

      const buildOutput = readdirSync(probe.getModuleBuildOutputPath());
      expect(buildOutput).toEqual([
        'entry-default-unsigned.hap',
        'entry-default-signed.hap',
        'pack.info'
      ].sort());

      // target中只有page/index
      const mainPagesPath = path.resolve(probe.getIntermediatesResProfilePath(), 'main_pages.json');
      const mainPagesOpt = Json5Reader.getJson5Obj(mainPagesPath);
      expect(mainPagesOpt.src).toEqual([
        'pages/index',
        'pages/page'
      ]);
    });
  });

  test.concurrent('stage app assembleHap esmodule', async () => {
    await initByStageEmptyApp(async (dir) => {
      const probe = new Probes(dir, resolve(dir, 'entry'));
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        tasks: 'assembleHap'
      });
      const result = runHvigor(dir, commands);
      expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();

      // 校验module.json5和loader.json里有对应配置
      const loaderJson = path.resolve(probe.getIntermediatesLoaderPath(), 'loader.json');
      expect(Json5Reader.getJson5Obj(loaderJson).compileMode).toEqual('esmodule');
      const moduleJson = path.resolve(probe.getIntermediatesRes(), 'module.json');
      const moduleJsonObj: ModuleOptObj = Json5Reader.getJson5Obj(moduleJson);
      expect(moduleJsonObj.module.compileMode).toEqual('esmodule');
      expect(moduleJsonObj.module.deviceTypes).toEqual([
        'default',
        'tablet'
      ]);

      const buildOutput = readdirSync(probe.getModuleBuildOutputPath());
      expect(buildOutput).toEqual([
        'entry-default-unsigned.hap',
        'entry-default-signed.hap',
        'pack.info'
      ].sort());
    });
  });

  test.concurrent('stage app assembleApp', async () => {
    await initByStageEmptyApp(async (dir) => {
      const commands = initExecuteCommand({
        mode: 'project',
        product: 'default',
        tasks: 'assembleApp'
      });
      const result = runHvigor(dir, commands);
      expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();
      const probe = new Probes(dir, resolve(dir, 'entry'));
      const buildOutput = readdirSync(probe.getProjectOutputPath());
      expect(buildOutput).toEqual([
        `${basename(dir)}-default-unsigned.app`,
        `${basename(dir)}-default-signed.app`,
        'pack.info',
        'pack.res'
      ].sort());
    });
  });

  test.concurrent('stage app test apiVersion in pack.info', async () => {
    await initByStageEmptyApp(async (dir) => {
      const commands = initExecuteCommand({
        mode: 'project',
        product: 'default',
        tasks: 'assembleApp'
      });
      const result = runHvigor(dir, commands);
      expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();
      const probe = new Probes(dir, resolve(dir));
      const packinfo = fse.readJsonSync(path.resolve(probe.getProjectOutputPath(), 'pack.info'));
      const buildProfile = Json5Reader.getJson5Obj(path.resolve(probe.getProjectPath(), 'build-profile.json5'));
      expect(packinfo.summary.modules[0]).toHaveProperty('apiVersion');
      expect(packinfo.summary.modules[0].apiVersion.compatible).toEqual(buildProfile.app.compatibleSdkVersion);
      expect(packinfo.summary.modules[0].apiVersion.target).toEqual(buildProfile.app.compileSdkVersion);
    });
  });

  test.concurrent('test build-profile.json5 module sequence', async () => {
    await initByStageEmptyApp(async (dir) => {
      const buildProfileJson5Path = path.resolve(dir, 'build-profile.json5');
      const json5Obj = Json5Reader.getJson5Obj(buildProfileJson5Path);
      fse.writeFileSync(buildProfileJson5Path, JSON.stringify({
        ...json5Obj,
        'modules': [
          {
            'name': 'feature',
            'srcPath': './feature',
            'targets': [
              {
                'name': 'default',
                'applyToProducts': [
                  'default'
                ]
              }
            ]
          },
          {
            'name': 'library',
            'srcPath': './library'
          },
          {
            'name': 'library1',
            'srcPath': './library1'
          },
          {
            'name': 'entry',
            'srcPath': './entry',
            'targets': [
              {
                'name': 'default',
                'applyToProducts': [
                  'default'
                ]
              }
            ]
          }
        ]
      }));

      const commands = initExecuteCommand({
        product: 'default',
        tasks: 'assembleHap'
      });
      const result = runHvigor(dir, commands);
      expect(result.stdout).toContain('BUILD SUCCESSFUL');
    });
  });
});

describe('test work dispatch', () => {
  test.concurrent('fa service assembleHap', async () => {
    await initByFABigService(async (dir) => {
      const commands = initExecuteCommand({
        mode: 'module',
        product: 'default',
        tasks: 'assembleHap'
      });
      const result = runHvigor(dir, commands);
      expect(result.stdout.includes('BUILD SUCCESSFUL')).toBeTruthy();
    });
  });
});
